#pragma once
#include "util.hpp"
#include <mutex>
#include <assert.h>
class user_table
{
public:
    user_table(
        std::string &host,
        std::string &user,
        std::string &pass,
        std::string &db,
        uint16_t port = 3306)
    {
        _mysql = mysql_util::mysql_create(host, user, pass, db, port);
        assert(_mysql != nullptr);
    }
    ~user_table()
    {
        mysql_util::mysql_destory(_mysql);
    }
    // 注册时新增用户信息
    bool insert(Json::Value &user)
    {
        Json::Value ret;
        if (select_by_name(user["username"].asCString(), ret))
        {
            DBG_LOG("user already exists");
            return false;
        }
        char command[1024] = {0};
        int l1 = sprintf(command, "insert user values(null,'%s','%s',1000,0,0);",
                         user["username"].asCString(), user["password"].asCString());
        if (l1 < 0)
        {
            ERR_LOG("command sprintf fail!:");
            return false;
        }
        std::string stmt_str(command);
        if (!mysql_util::mysql_exc(_mysql, stmt_str))
        {
            ERR_LOG("command mysql_exc fail!:");
            return false;
        }
        return true;
    }
    // 登录时验证用户信息并获取
    bool login(Json::Value &user)
    {
        char command[1024] = {0};
        int l1 = sprintf(command, "select id, score, total_count, win_count from user where username='%s' and password='%s';",
                         user["username"].asCString(), user["password"].asCString());
        if(l1<0)
        {
            DBG_LOG("sprintf fail!!!!");
        }
        std::string mycommand(command);
        std::unique_lock<std::mutex>(_mutex);
        MYSQL_RES *res=NULL;
        {
            bool ret = mysql_util::mysql_exc(_mysql, mycommand);
            if (ret == false)
            {
                ERR_LOG("command mysql_exc fail!:");
                return false;
            }
            res = mysql_store_result(_mysql);
            if (res == NULL)
            {
                ERR_LOG("mysql_store_result fail!:");
                return false;
            }
        }
        uint64_t row = mysql_num_rows(res);
        if (row != 1)
        {
            ERR_LOG("the query result is not unique");
            return false;
        }
        MYSQL_ROW rows = mysql_fetch_row(res);
        user["id"] = std::stol(rows[0]);
        user["score"] = std::stol(rows[1]);
        user["total_count"] = std::stol(rows[2]);
        user["win_count"] = std::stol(rows[3]);
        mysql_free_result(res);
        return true;
    }
    // 通过用户名获取用户信息
    bool select_by_name(const std::string &name, Json::Value &mess)
    {
        char command[1024] = {0};
        int l1 = sprintf(command, "select id, score, total_count, win_count from user where username='%s';", name.c_str());
        std::string mycommand(command);
        std::unique_lock<std::mutex>(_mutex);
        MYSQL_RES *res=NULL;
        {
            bool ret = mysql_util::mysql_exc(_mysql, mycommand);
            if (ret == false)
            {
                ERR_LOG("command mysql_exc fail!:");
                return false;
            }
            res = mysql_store_result(_mysql);
            if (res == NULL)
            {
                ERR_LOG("mysql_store_result fail!:");
                return false;
            }
        }
        uint64_t row = mysql_num_rows(res);
        if (row != 1)
        {
            ERR_LOG("the query result is not unique");
            return false;
        }
        MYSQL_ROW rows = mysql_fetch_row(res);
        mess["id"] = std::stol(rows[0]);
        mess["score"] = std::stol(rows[1]);
        mess["total_count"] = std::stol(rows[2]);
        mess["win_count"] = std::stol(rows[3]);
        mysql_free_result(res);
        return true;
    }
    // 通过用户id获取用户信息
    bool select_by_id(uint64_t id, Json::Value &mess)
    {
        char command[1024] = {0};
        int l1 = sprintf(command, "select id,username, score, total_count, win_count from user where id=%ld;", id);
        std::string mycommand(command);
        std::unique_lock<std::mutex>(_mutex);
        MYSQL_RES *res=NULL;
        {
            bool ret = mysql_util::mysql_exc(_mysql, mycommand);
            if (ret == false)
            {
                ERR_LOG("command mysql_exc fail!:");
                return false;
            }
            res = mysql_store_result(_mysql);
            if (res == NULL)
            {
                ERR_LOG("mysql_store_result fail!:");
                return false;
            }
        }
        uint64_t row = mysql_num_rows(res);
        if (row != 1)
        {
            ERR_LOG("the query result is not unique");
            return false;
        }
        MYSQL_ROW rows = mysql_fetch_row(res);
        mess["id"]=std::stol(rows[0]);
        mess["username"] = rows[1];
        mess["score"] = std::stol(rows[2]);
        mess["total_count"] = std::stol(rows[3]);
        mess["win_count"] = std::stol(rows[4]);
        mysql_free_result(res);
        return true;
    }
    // 对战胜利时修改数据库
    bool win(uint64_t id)
    {
        char command[1024] = {0};
        int l1 = sprintf(command, "update user set score=score+30, total_count=total_count+1, win_count=win_count+1 where id=%zu;", id);
        std::string mycommand(command);
        bool ret = mysql_util::mysql_exc(_mysql, mycommand);
        if (ret == false)
        {
            ERR_LOG("update win date fail!:");
            return false;
        }
        return true;
    }
    // 对战失败时修改数据库
    bool lose(uint64_t id)
    {
        char command[1024] = {0};
        int l1 = sprintf(command, "update user set score=score-30, total_count=total_count+1 where id=%zu;", id);
        std::string mycommand(command);
        bool ret = mysql_util::mysql_exc(_mysql, mycommand);
        if (ret == false)
        {
            ERR_LOG("update lose date fail!:");
            return false;
        }
        return true;
    }

private:
    MYSQL *_mysql;
    std::mutex _mutex;
};